"""
API测试基类
提供API测试的通用功能和基础设置
"""

import pytest
from typing import Dict, Any, Optional
from unittest.mock import Mock, patch
from fastapi.testclient import TestClient

from app.main import app
from tests.utils.test_helpers import (
    create_test_client,
    mock_db_session,
    create_mock_user,
    create_auth_headers,
    create_json_headers,
    combine_headers,
    assert_response_status,
    assert_response_data
)


class BaseAPITest:
    """API测试基类"""
    
    # 测试客户端
    client: TestClient = None
    
    # 模拟对象
    mock_db = None
    mock_current_user = None
    
    # 认证令牌
    access_token: str = "mock_access_token"
    refresh_token: str = "mock_refresh_token"
    
    # 默认测试数据
    default_test_data: Dict[str, Any] = {}
    
    @classmethod
    def setup_class(cls):
        """测试类设置"""
        cls.client = create_test_client(app)
    
    def setup_method(self):
        """每个测试方法前的设置"""
        # 创建模拟数据库会话
        self.mock_db = mock_db_session()
        
        # 创建模拟当前用户
        self.mock_current_user = create_mock_user()
        
        # 初始化默认测试数据
        self.default_test_data = {
            "test_user": self.mock_current_user,
            "access_token": self.access_token,
            "refresh_token": self.refresh_token
        }
    
    def teardown_method(self):
        """每个测试方法后的清理"""
        pass
    
    def get_auth_headers(self) -> Dict[str, str]:
        """获取认证头"""
        return create_auth_headers(self.access_token)
    
    def get_json_headers(self) -> Dict[str, str]:
        """获取JSON内容头"""
        return create_json_headers()
    
    def get_combined_headers(self, *additional_headers) -> Dict[str, str]:
        """获取组合头"""
        base_headers = [self.get_json_headers()]
        if additional_headers:
            base_headers.extend(additional_headers)
        return combine_headers(*base_headers)
    
    def create_test_user(self, user_id: int = 1, **kwargs) -> Mock:
        """创建测试用户"""
        return create_mock_user(user_id, **kwargs)
    
    # 通用API测试方法
    
    def test_get_request(self, endpoint: str, expected_status: int = 200, 
                        headers: Optional[Dict[str, str]] = None,
                        params: Optional[Dict[str, Any]] = None) -> Any:
        """测试GET请求"""
        if headers is None:
            headers = self.get_auth_headers()
            
        response = self.client.get(endpoint, headers=headers, params=params)
        assert_response_status(response, expected_status)
        return response
    
    def test_post_request(self, endpoint: str, data: Dict[str, Any], 
                         expected_status: int = 200,
                         headers: Optional[Dict[str, str]] = None) -> Any:
        """测试POST请求"""
        if headers is None:
            headers = self.get_combined_headers(self.get_auth_headers())
            
        response = self.client.post(endpoint, json=data, headers=headers)
        assert_response_status(response, expected_status)
        return response
    
    def test_put_request(self, endpoint: str, data: Dict[str, Any], 
                        expected_status: int = 200,
                        headers: Optional[Dict[str, str]] = None) -> Any:
        """测试PUT请求"""
        if headers is None:
            headers = self.get_combined_headers(self.get_auth_headers())
            
        response = self.client.put(endpoint, json=data, headers=headers)
        assert_response_status(response, expected_status)
        return response
    
    def test_delete_request(self, endpoint: str, expected_status: int = 200,
                           headers: Optional[Dict[str, str]] = None) -> Any:
        """测试DELETE请求"""
        if headers is None:
            headers = self.get_auth_headers()
            
        response = self.client.delete(endpoint, headers=headers)
        assert_response_status(response, expected_status)
        return response
    
    def test_patch_request(self, endpoint: str, data: Dict[str, Any], 
                          expected_status: int = 200,
                          headers: Optional[Dict[str, str]] = None) -> Any:
        """测试PATCH请求"""
        if headers is None:
            headers = self.get_combined_headers(self.get_auth_headers())
            
        response = self.client.patch(endpoint, json=data, headers=headers)
        assert_response_status(response, expected_status)
        return response
    
    # 通用断言方法
    
    def assert_success_response(self, response, expected_data: Optional[Dict[str, Any]] = None):
        """断言成功响应"""
        assert_response_status(response, 200)
        if expected_data:
            assert_response_data(response, expected_data)
    
    def assert_created_response(self, response, expected_data: Optional[Dict[str, Any]] = None):
        """断言创建成功响应"""
        assert_response_status(response, 201)
        if expected_data:
            assert_response_data(response, expected_data)
    
    def assert_bad_request(self, response):
        """断言错误请求"""
        assert_response_status(response, 400)
    
    def assert_unauthorized(self, response):
        """断言未授权"""
        assert_response_status(response, 401)
    
    def assert_forbidden(self, response):
        """断言禁止访问"""
        assert_response_status(response, 403)
    
    def assert_not_found(self, response):
        """断言未找到"""
        assert_response_status(response, 404)
    
    def assert_validation_error(self, response):
        """断言验证错误"""
        assert_response_status(response, 422)
    
    def assert_internal_error(self, response):
        """断言内部错误"""
        assert_response_status(response, 500)


# 为兼容性提供全局函数
def setup_test_client():
    """设置测试客户端"""
    return create_test_client(app)


def setup_mock_db():
    """设置模拟数据库"""
    return mock_db_session()


def setup_test_user(user_id: int = 1, **kwargs):
    """设置测试用户"""
    return create_mock_user(user_id, **kwargs)